package com.iplant.base.utils.annotation.condition;

import com.iplant.base.po.OutResult;
import com.iplant.base.po.enums.ExceptionTypes;
import com.iplant.base.utils.general.StringUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * @author xiuto
 */
public class DBConditionValue {
    /**
     * 表字段名称  从DBField或DBJoin中获取
     */
    public String name = "";

    /**
     * 数据类型
     */
    public String TypeName = "";
    /**
     * 显示名称
     */
    public String viewName = "";
    /**
     * 表别名
     */
    public String tableAsName = "t";
    /**
     * 查询参数名称
     */
    public String ParamName = "";
    /**
     * 查询参数名称2
     */
    public String ParamName2 = "";


    /**
     * 是否为必需值
     */
    public boolean MustCondition = false;
    /**
     * 查询参数与字段比较方式
     */
    public DBCondition.DBCompareType CompareType = DBCondition.DBCompareType.eq;

    public boolean Exist = false;


    /**
     * 在Controller中剔除参数无效的条件
     * 在BaseDao中判断必给条件是否给出
     *
     * @param wValue
     * @return
     */
    public String ToString(Object wValue, Object wValue2) {
        String wResult = "";
        if (StringUtils.isEmpty(this.name) || StringUtils.isEmpty(this.tableAsName) || StringUtils.isEmpty(this.ParamName)) {
            return wResult;
        }
        List<String> wValueStringList;
        switch (this.CompareType) {
            case eq:
            case in:
                wValueStringList = StringUtils.splitListObject(wValue, ",");
                if(wValueStringList.size()==0){
                    return wResult;
                }else  if(wValueStringList.size()==1){
                    wResult = StringUtils.Format(" ( {0}.{1} = :{2} ) ", tableAsName, name, ParamName);
                }else{
                    wResult = StringUtils.Format(" ( {0}.{1} in (''{2}'') ) ", tableAsName, name,
                            StringUtils.JoinCollection("','", wValueStringList));
                }
                break;
            case ne:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( {0}.{1} != :{2} ) ", tableAsName, name, ParamName);
                }
                break;
            case gt:
                //大于
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( ({0}.{1} < :{2}) ) ", tableAsName, name, ParamName);
                }
                break;
            case lt:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    //小于
                    wResult = StringUtils.Format(" ( {0}.{1} > :{2} ) ", tableAsName, name, ParamName);
                }
                break;
            case gtLt:

                if (!StringUtils.IsEmptyCondition(wValue2) && !StringUtils.IsEmptyCondition(wValue)) {
                    wResult = StringUtils.Format(" ( {0}.{1} > :{2} and  {0}.{1} < :{3} ) ", tableAsName, name,
                            ParamName,
                            ParamName2);
                } else {

                    if (!StringUtils.IsEmptyCondition(wValue)) {
                        wResult = StringUtils.Format(" ( {0}.{1} >  :{2} ) ", tableAsName, name,
                                ParamName);
                    }
                    if (!StringUtils.IsEmptyCondition(wValue2)) {
                        wResult = StringUtils.Format(" ( {0}.{1} <  :{2} ) ", tableAsName, name,
                                ParamName2);
                    }
                }
                break;
            case ge:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( {0}.{1} <= :{2} ) ", tableAsName, name, ParamName);
                }
                break;
            case le:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( {0}.{1} >= :{2} ) ", tableAsName, name, ParamName);
                }
                break;
            case geLe:
                if (!StringUtils.IsEmptyCondition(wValue2) && !StringUtils.IsEmptyCondition(wValue)) {
                    wResult = StringUtils.Format(" ( {0}.{1} >= :{2} and  {0}.{1} <= :{3} ) ", tableAsName, name,
                            ParamName,
                            ParamName2);
                } else {
                    if (!StringUtils.IsEmptyCondition(wValue)) {
                        wResult = StringUtils.Format(" ( {0}.{1} >=  :{2} ) ", tableAsName, name,
                                ParamName);
                    }
                    if (!StringUtils.IsEmptyCondition(wValue2)) {
                        wResult = StringUtils.Format(" ( {0}.{1} <=  :{2} ) ", tableAsName, name,
                                ParamName2);
                    }
                }
                break;
            case geLt:
                if (!StringUtils.IsEmptyCondition(wValue2) && !StringUtils.IsEmptyCondition(wValue)) {
                    wResult = StringUtils.Format(" ( {0}.{1} > :{2} and  {0}.{1} <= :{3} ) ", tableAsName, name,
                            ParamName,
                            ParamName2);

                } else {

                    if (!StringUtils.IsEmptyCondition(wValue)) {
                        wResult = StringUtils.Format(" ( {0}.{1} >  :{2} ) ", tableAsName, name,
                                ParamName);
                    }
                    if (!StringUtils.IsEmptyCondition(wValue2)) {
                        wResult = StringUtils.Format(" ( {0}.{1} <=  :{2} ) ", tableAsName, name,
                                ParamName2);
                    }
                }


                break;
            case gtLe:
                if (!StringUtils.IsEmptyCondition(wValue2) && !StringUtils.IsEmptyCondition(wValue)) {
                    wResult = StringUtils.Format(" ( {0}.{1} >= :{2} and  {0}.{1} < :{3} ) ", tableAsName, name,
                            ParamName,
                            ParamName2);
                } else {
                    if (!StringUtils.IsEmptyCondition(wValue)) {
                        wResult = StringUtils.Format(" ( {0}.{1} >=  :{2} ) ", tableAsName, name,
                                ParamName);
                    }
                    if (!StringUtils.IsEmptyCondition(wValue2)) {
                        wResult = StringUtils.Format(" ( {0}.{1} <  :{2} ) ", tableAsName, name,
                                ParamName2);
                    }
                }
                break;
            case like:

                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( {0}.{1} like concat(''%'', :{2},''%'')) ", tableAsName, name,
                            ParamName);
                }

                break;
            case leftLike:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( {0}.{1} like concat(:{2},''%'')) ", tableAsName, name, ParamName);
                }
                break;
            case rightLike:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( {0}.{1} like concat(''%'', :{2})) ", tableAsName, name, ParamName);
                }
                break;

            case likeProp:

                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" (  :{2} like concat(''%'', {0}.{1},''%'')) ", tableAsName, name,
                            ParamName);
                }

                break;
            case leftLikeProp:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( :{2} like concat({0}.{1},''%'')) ", tableAsName, name, ParamName);
                }
                break;
            case rightLikeProp:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    wResult = StringUtils.Format(" ( :{2} like concat(''%'', {0}.{1})) ", tableAsName, name, ParamName);
                }
                break;

            case notLike:
                wResult = StringUtils.Format(" ( {0}.{1} not like concat(''%'', :{2},''%'')) ", tableAsName, name,
                        ParamName);
                break;
            case notIn:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} in   (''{2}'') ) ) ", tableAsName, name,
                            StringUtils.JoinObject("','", wValue2));
                } else
                    wResult = StringUtils.Format(" ( {0}.{1} not in (''{2}'') ) ", tableAsName, name,
                            StringUtils.JoinObject("','", wValue));
                break;
            case findInSet:
                wValueStringList = StringUtils.splitListObject(wValue, ",");
                for (int i = 0; i < wValueStringList.size(); i++) {
                    if (i == 0) {
                        wResult += StringUtils.Format(" ( FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                wValueStringList.get(i));
                    } else if (i == wValueStringList.size() - 1) {
                        wResult += StringUtils.Format(" and FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                wValueStringList.get(i));
                    } else {
                        wResult += StringUtils.Format(" and FIND_IN_SET( ''{2}'' ,{0}.{1} ) ", tableAsName, name,
                                wValueStringList.get(i));
                    }
                }
                break;
            case findInSetOR:
                wValueStringList = StringUtils.splitListObject(wValue, ",");
                for (int i = 0; i < wValueStringList.size(); i++) {
                    if (i == 0) {
                        wResult += StringUtils.Format(" ( FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                wValueStringList.get(i));
                    } else if (i == wValueStringList.size() - 1) {
                        wResult += StringUtils.Format(" OR FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                wValueStringList.get(i));
                    } else {
                        wResult += StringUtils.Format(" OR FIND_IN_SET( ''{2}'' ,{0}.{1} ) ", tableAsName, name,
                                wValueStringList.get(i));
                    }
                }
                break;
            case NotFindInSet:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wValueStringList = StringUtils.splitListObject(wValue2, ",");
                    for (int i = 0; i < wValueStringList.size(); i++) {
                        if (i == 0) {
                            wResult += StringUtils.Format(" ( FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        } else if (i == wValueStringList.size() - 1) {
                            wResult += StringUtils.Format(" and FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        } else {
                            wResult += StringUtils.Format(" and FIND_IN_SET( ''{2}'' ,{0}.{1} ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        }
                    }
                } else {
                    wValueStringList = StringUtils.splitListObject(wValue, ",");
                    for (int i = 0; i < wValueStringList.size(); i++) {
                        if (i == 0) {
                            wResult += StringUtils.Format(" ( !FIND_IN_SET( ''{2}'' ,{0}.{1} ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        } else if (i == wValueStringList.size() - 1) {
                            wResult += StringUtils.Format(" AND !FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        } else {
                            wResult += StringUtils.Format(" AND !FIND_IN_SET( ''{2}'' ,{0}.{1} ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        }
                    }
                }
                break;
            case NotFindInSetOR:

                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wValueStringList = StringUtils.splitListObject(wValue2, ",");
                    for (int i = 0; i < wValueStringList.size(); i++) {
                        if (i == 0) {
                            wResult += StringUtils.Format(" ( FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        } else if (i == wValueStringList.size() - 1) {
                            wResult += StringUtils.Format(" OR FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        } else {
                            wResult += StringUtils.Format(" OR FIND_IN_SET( ''{2}'' ,{0}.{1} ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        }
                    }
                } else {
                    wValueStringList = StringUtils.splitListObject(wValue, ",");
                    for (int i = 0; i < wValueStringList.size(); i++) {
                        if (i == 0) {
                            wResult += StringUtils.Format(" ( !FIND_IN_SET( ''{2}'' ,{0}.{1} ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        } else if (i == wValueStringList.size() - 1) {
                            wResult += StringUtils.Format(" OR !FIND_IN_SET( ''{2}'' ,{0}.{1} ) ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        } else {
                            wResult += StringUtils.Format(" OR !FIND_IN_SET( ''{2}'' ,{0}.{1} ) ", tableAsName, name,
                                    wValueStringList.get(i));
                        }
                    }
                }
                break;
            case Combine:
                if (StringUtils.isNotEmpty(ParamName2) && wValue2 != null && StringUtils.isNotEmpty(wValue2.toString())
                        && !ParamName2.equalsIgnoreCase(ParamName)) {
                    wResult = StringUtils.Format(" ( {0}.{1} =  :{2} ) ", tableAsName, name,
                            ParamName2);
                } else {
                    //与
                    wResult = StringUtils.Format(" ( {0}.{1} = :{2}  or (:{2}&{0}.{1})>0) ", tableAsName, name, ParamName);
                }
                break;

        }


        return wResult;
    }

    public DBConditionValue(DBCondition wDBCondition, Field wField) {
        //name = wDBCondition.N;
        viewName = wField.getName();
        TypeName = wField.getType().getSimpleName();
        ParamName = wDBCondition.ParamName();
        ParamName2 = wDBCondition.ParamName2();
        CompareType = wDBCondition.CompareType();
        MustCondition = wDBCondition.MustCondition();
        if (StringUtils.isEmpty(ParamName)) ParamName = viewName;
        if (StringUtils.isEmpty(ParamName2)) ParamName2 = viewName;

    }

    /**
     * 检查输入数据是否有效
     *
     * @param wParams
     * @param wErrorCode
     * @return
     */
    public boolean CheckValue(Map<String, Object> wParams, OutResult<Integer> wErrorCode) {
        boolean wResult = true;

        if (this.MustCondition) {

            if (!CheckValue(wParams)) {
                //必要条件未给出抛出参数错误
                wErrorCode.Result = ExceptionTypes.Parameter.getValue();
                wResult = false;
            }
        } else {
            if (!CheckValue(wParams)) {
                //条件参数未给忽略此参数
                wResult = false;
            }
            //判断值类型 是否为空判断
        }
        return wResult;
    }

    private boolean CheckValue(Map<String, Object> wParams) {
        boolean wResult = true;
        switch (this.CompareType) {

            case eq:
            case notLike:
            case in:
            case findInSet:
            case findInSetOR:
                if (!wParams.containsKey(this.ParamName) || !StringUtils.IsNotEmptyValue(wParams.get(this.ParamName),
                        this.TypeName)) {
                    wResult = false;
                }

                break;
            case ne:
            case gt:
            case lt:
            case ge:
            case le:
            case gtLt:
            case geLe:
            case geLt:
            case gtLe:
            case like:
            case leftLike:
            case rightLike:
            case likeProp:
            case leftLikeProp:
            case rightLikeProp:
            case notIn:
            case NotFindInSet:
            case NotFindInSetOR:
            case Combine:
                if ((!wParams.containsKey(this.ParamName) || !StringUtils.IsNotEmptyValue(wParams.get(this.ParamName)
                        , this.TypeName))
                        && (!wParams.containsKey(this.ParamName2) || !StringUtils.IsNotEmptyValue(wParams.get(this.ParamName2), this.TypeName))) {
                    wResult = false;
                }
                break;
            default:
                wResult = false;
                break;
        }
        return wResult;

    }


}
